import pygtk
pygtk.require('2.0')
import gtk
import lesson
import os

TYPING_ROOT = os.path.dirname(os.path.abspath(__file__))
while(os.path.isfile(TYPING_ROOT)):
    TYPING_ROOT = os.path.dirname(TYPING_ROOT)

#class to load a lesson plan from a file
class Memory:
    def __init__(self, callbackFunc, hbox, labelDict, lessons, name):
        self.setup(callbackFunc, hbox, labelDict, lessons, name)

    def __init__(self, callbackFunc, hbox, labelDict, lessons):
        self.setup(callbackFunc, hbox, labelDict, lessons, "unknown")

    def setup(self, callbackFunc, hbox, labelDict, lessons, name):
        self.myName = name
  
        badLessons = []      
        #Try loading from name
        try:
            lessonFile = file(TYPING_ROOT+os.sep+self.myName+".mem","r")         
        except IOError, error:            
            print "unable to read file %s : %s" % (TYPING_ROOT+os.sep+self.myName+".mem", error)
            print "if you believe the user should have memory, please error-check."
            return

        #If the file exists, we read in the history from it.
        #There should, theoretically, be one word per line,
        #Then the associated lesson and word number
        lineInput = lessonFile.readline()
        if lineInput.find("\n") != -1:
            lineInput = lineInput[0:lineInput.find("\n")]
        while lineInput != '':
            try:
                #Lines are in the format: Word, WordNum, LessonName
                base = lineInput
                word = lineInput[0:lineInput.find(", ")]
                lineInput = lineInput[lineInput.find(", ")+2:]
                wordNum = int(lineInput[0:lineInput.find(", ")])
                lineInput = lineInput[lineInput.find(", ")+2:]
                lesson = lineInput
            except ValueError:
                #A value error could occur if we try to cast a non-number-only string as an integer
                print "Value Error (Invalid Word Number), Skipping Line: %s" % base
            else:
                #Check to see if this word in memory is the same as the word the lesson has at this slot
                wordsInLessons = lessons.getLessonWords(lesson)
                #If words in lesson is {}, then there is no such lesson, so we don't want to make a label
                if(not wordsInLessons == {}):
                    wordCheck = wordsInLessons[wordNum-1]
                    #If the word is teh same, we can make a label.  Otherwise, we know this whole lesson is bad
                    if(wordCheck == word):
                        Lab = gtk.Label(word)
                        labelDict[(wordNum, lesson)] = Lab
                        Lab.show()
                    else:
                        if(not contains(badLessons,lesson)):
                            badLessons.append(lesson)
            lineInput = lessonFile.readline()
            if lineInput.find("\n") != -1:
                lineInput = lineInput[0:lineInput.find("\n")]

        #Get the set of keys.  Since we'll be removing all
        #things with bad lessons, we need an original copy to scroll through
        oldKeys = self.sortKeys(labelDict.keys())
        for x in oldKeys:
            if(contains(badLessons,x[1])):
                del labelDict[x]

        #Get the set of keys, to scroll through to pack the memory box.
        newKeys = self.sortKeys(labelDict.keys())
        for x in newKeys:
            EBox = gtk.EventBox()
            hbox.pack_start(EBox, False, True, 5)
            EBox.show()
            EBox.connect("button-press-event", callbackFunc, x[0])
            EBox.add(labelDict[x])
        #Close the file
        del lessonFile

    #Standard mergeSort merge algorithm.
    def merge(self, left, right):
        leftIndex = 0;
        rightIndex = 0;
        result = []
        while (leftIndex < len(left) and rightIndex < len(right)):
            if(strictlyLess(left[leftIndex], right[rightIndex])):
                result.append(left[leftIndex])
                leftIndex = leftIndex+1
            else:
                result.append(right[rightIndex])
                rightIndex = rightIndex+1
        while(leftIndex < len(left)):
            result.append(left[leftIndex])
            leftIndex = leftIndex+1
        while(rightIndex < len(right)):
            result.append(right[rightIndex])
            rightIndex = rightIndex+1
        return result                

    #Standard mergeSort algorithm.
    def sortKeys(self, keyList):
        if(len(keyList) <= 1):
            return keyList
        else:
            mid = len(keyList) / 2
            left = self.sortKeys(keyList[0:mid])
            right = self.sortKeys(keyList[mid:])
            return self.merge(left, right)

    #Write the words contained in memory (the label dictionary) out to the file we are reading from.              
    def writeMem(self, labelDict):
        try:
            #If the file already exists, delete it
            lessonFile = file(TYPING_ROOT+os.sep+self.myName+".mem","w")         
            del lessonFile
            os.remove(TYPING_ROOT+os.sep+self.myName+".mem")
            #Make sure it was successfully removed, and create a new copy
            try:
                lessonFile = file(TYPING_ROOT+os.sep+self.myName+".mem","w")         
            except IOError, error:
                print "unable to write file %s : %s" % (TYPING_ROOT+os.sep+self.myName+".mem", error)
                print "if you believe the user should have memory, please error-check."
                return
        except IOError, error:
            print "unable to write file %s : %s" % (TYPING_ROOT+os.sep+self.myName+".mem", error)
            print "if you believe the user should have memory, please error-check."
            return

        toAdd = ""
        #Sort the keys, so we store in alphabetical order of lessons, numerical order within the lesson
        keys = self.sortKeys(labelDict.keys())
        for x in keys:
            toAdd = toAdd + labelDict[x].get_text()+", "+str(x[0])+", "+x[1]+"\n"
        lessonFile.write(toAdd);

        del lessonFile        

#Defines strictly less than, for two tuples of (position, lesson).
#Returns true if tuple1 is strictly less than tuple2, defined as:
#if lesson1 < lesson2, then true.
#if lesson2 < lesson1, then false
#if lesson1 = lesson2 then, position1 < position2
def strictlyLess(tuple1, tuple2):
    if(tuple1[1] < tuple2[1]):
        return True
    elif(tuple1[1] == tuple2[1]):
        if(tuple1[0] < tuple2[0]):
            return True
    return False

#Determines if a given array contains a given value within it.
#Returns true if it does
def contains(array, value):
    for x in range(0,len(array)):
        if array[x] == value:
            return True
    return False